using System;
using System.Collections.Generic;
using System.ComponentModel;
using ZoneFiveSoftware.Common.Data;
using ZoneFiveSoftware.Common.Data.Fitness;
using ZoneFiveSoftware.Common.Data.Measurement;
using FilteredStatistics.Common;
using FilteredStatistics.View;
using FilteredStatistics.Controller;

namespace FilteredStatistics.Data
{
    class TimeLapNamedZone : INamedZone
    {
        public TimeLapNamedZone(IActivity activity, int lapIndex, TimeSpan startTimeOffset, TimeSpan endTimeOffset)
        {
            m_ActivityCallbackHelper = new ActivityDataChangedHelper(m_Activity);
            m_ActivityCallbackHelper.PropertyChanged += new PropertyChangedEventHandler(OnActivityDataChanged);

            m_LapIndex = lapIndex;
            Init(activity, startTimeOffset, endTimeOffset);
        }

        void OnActivityDataChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "Activity.Duration")
            {
                m_ValidTimesDirty = true;
                TriggerValidTimesChanged();
            }
        }

#region INamedZone members

        public String Name
        {
            get
            {
                String lapName = String.Format(PluginView.GetLocalizedString("LapNumberText"), m_LapIndex + 1);

                lapName += String.Format(" [{0}; {1}]", m_StartTimeOffset.ToString(), m_EndTimeOffset.ToString());

                return lapName;
            }
        }

        public IValueRangeSeries<DateTime> ValidTimes
        {
            get
            {
                RefreshValidTimes();

                return m_ValidTimes; 
            }
        }

        public event PropertyChangedEventHandler ValidTimesChanged;

#endregion

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            TimeLapNamedZone namedZone = obj as TimeLapNamedZone;

            if (namedZone != null)
            {
                // Diff distance with an epsilon of 0.001 to prevent rounding errors
                return namedZone.m_LapIndex == m_LapIndex &&
                       namedZone.m_StartTimeOffset == m_StartTimeOffset &&
                       namedZone.m_EndTimeOffset == m_EndTimeOffset;
            }

            return base.Equals(obj);
        }

        protected void TriggerValidTimesChanged()
        {
            if (ValidTimesChanged != null)
            {
                ValidTimesChanged(this, new PropertyChangedEventArgs("ValidTimes"));
            }
        }

        private void RefreshValidTimes()
        {
            if (m_ValidTimesDirty)
            {
                m_ValidTimesDirty = false;

                m_ValidTimes.Clear();

                if (Activity != null)
                {
                    ActivityInfo activityInfo = ActivityInfoCache.Instance.GetInfo(Activity);
                    IValueRange<DateTime> rangeWithPauses = Utils.AddPausesToRange(new ValueRange<DateTime>(activityInfo.ActualTrackStart + m_StartTimeOffset, activityInfo.ActualTrackStart + m_EndTimeOffset), Activity);

                    m_ValidTimes.Add(new ValueRange<DateTime>(rangeWithPauses.Lower, rangeWithPauses.Upper));
                }

                TriggerValidTimesChanged();
            }
        }

        public void Init(IActivity activity, TimeSpan startTimeOffset, TimeSpan endTimeOffset)
        {
            m_StartTimeOffset = startTimeOffset;
            m_EndTimeOffset = endTimeOffset;

            Activity = activity;
        }

        public IActivity Activity
        {
            get { return m_Activity; }
            set
            {
                if (Activity != value)
                {
                    m_Activity = value;
                    m_ActivityCallbackHelper.Activity = m_Activity;

                    m_ValidTimesDirty = true;
                    TriggerValidTimesChanged();
                }
            }
        }

        private IActivity m_Activity;
        private ActivityDataChangedHelper m_ActivityCallbackHelper = null;
        private int m_LapIndex = -1;
        private TimeSpan m_StartTimeOffset;
        private TimeSpan m_EndTimeOffset;
        private IValueRangeSeries<DateTime> m_ValidTimes = new ValueRangeSeries<DateTime>();
        private bool m_ValidTimesDirty = false;
    }
}
